/*
#Copyright (c) 2013, Philippe Bordron <philippe.bordron@gmail.com>
#
# This file is part of SIPPER.
#
# DCC is free software: you can redistribute it and/or modify
# it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DCC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU LESSER GENERAL PUBLIC LICENSE for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# along with SIPPER.  If not, see <http://www.gnu.org/licenses/>
*/
package combi.wip.sipper.io;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import combi.utils.Couple;
import combi.wip.utils.Bloc;

public class IObioASPkSIPs {

	/**
	 * Translate bioASP k-SIPs into normal ones.
	 * 
	 * process:
	 * 1 - get a String bloc corresponding to a k-SIPs
	 * 2 - transform each path of the bloc into a path by using an array to put them in the right order
	 * 3 - write the k-SIP into a standard format.
	 * 
	 */


	private static String END = "";
	private static String BEGIN = "(?:(.+) shortest paths from reaction (\\S+) to (\\S+).*)";

	public static List<Bloc<String, String>> load(String fileIn)throws IOException
	{
		BufferedReader in;
		String ch = null;
		in = new BufferedReader(new FileReader(fileIn));
		boolean inBloc = false; // indicates if we parse a kSIP.
		String strBloc = "";
		List<Bloc<String, String>> list = new ArrayList<Bloc<String,String>>();
		Bloc<String, String> bloc = null;
		while ((ch=in.readLine())!=null)
		{
			//detecting the end of the bloc end threat it.
			if(ch.equals(END))
			{
				//System.out.println("end");
				bloc = generateBloc(strBloc);
				if (bloc != null)
				{
					list.add(bloc);
				}
				inBloc = false;
				strBloc ="";
			}

			//dectecting the begining of a bloc
			if (ch.matches(BEGIN))
			{			
				//System.out.println("begin");
				// if the previous bloc is not closed before, then closed it and begin the new one. 
				if (inBloc)
				{
					bloc = generateBloc(strBloc);
					if (bloc != null)
					{
						list.add(bloc);
					}
				}
				inBloc = true;	
				strBloc ="";		
			}
			// completing the bloc.
			strBloc += ch + "\n";
		}
		if (inBloc)
		{
			//System.out.println("Fin : \n" + strBloc);
			bloc = generateBloc(strBloc);
			if (bloc != null)
			{
				list.add(bloc);
			}		
		}	
		in.close();
		return list;
	}
	

	private static String Ke = "(?:\\s+([0-9]+):)";
	private static String ELEM = "(?:[^\\s()]+)";
	private static String ARC = "(?:\\s+("+ ELEM+ ")\\(("+ELEM +")\\)"+"\\s+->\\s+"+"("+ ELEM+ ")\\(("+ELEM +")\\)"+ ")";

	
	private static Bloc<String, String> generateBloc(String strBloc) {
		//System.out.println(strBloc);
		Bloc<String, String> result = null;
		Pattern reco = Pattern.compile(BEGIN);
		Pattern recoK = Pattern.compile(Ke);
		Pattern recoArc = Pattern.compile(ARC);
		Matcher m;
		String first = null;
		if (!strBloc.isEmpty())
		{
			String[] parts = strBloc.split("\n");
			String chID = parts[0];
			m = reco.matcher(chID);
			if (m.find())
			{
				String id = m.group(2) + "->" + m.group(3);	
				first = m.group(2);
				result = new Bloc<String, String>(id);
				Map<String,String> path=new HashMap<String,String>();
				Map<String,String> asso=new HashMap<String,String>();
				for (int i = 1; i< parts.length; i++)
				{
					String ch = parts[i]; 
					m = recoArc.matcher(ch); // new arc
					if (m.find())
					{
						//System.err.println(ch);
						path.put(m.group(1), m.group(3));
						asso.put(m.group(1), m.group(2));
						asso.put(m.group(3), m.group(4));
					}

					m = recoK.matcher(ch); // new path (with number)
					if (m.find())
					{
						//System.err.println(ch);
						if (!path.isEmpty())
						{
							List<String> lr = mapToPath(path, first);
							List<String> lg = listReactionToGene(lr, asso);
							result.add(lr, lg);
							path.clear();
						}
					}
				}
				if (!path.isEmpty())
				{
					List<String> lr = mapToPath(path, first);
					List<String> lg = listReactionToGene(lr, asso);
					result.add(lr, lg);
					path.clear();
				}
			}
		}
		return result;
	}

	private static List<String> listReactionToGene(List<String> lr,
			Map<String, String> asso) {
		List<String> result = new ArrayList<String>(lr.size());
		for (String r : lr)
		{
			result.add(asso.get(r));
		}
		return result;
	}

	private static List<String> mapToPath(Map<String, String> successorMap, String first)
	{
		List<String> result = new ArrayList<String>(successorMap.size());
		String enCours = first;
		boolean fini = false;
		do
		{
			result.add(enCours);
			enCours = successorMap.get(enCours);
			fini = enCours == null;
		}
		while (!fini);
		return result;
	}
	
	public static void main(String[] args) throws IOException
	{
		String fileIn = args[0];
		String fileOut = args[1];
		
		BufferedWriter out;
		out = new BufferedWriter(new FileWriter(fileOut));
		
		for(Bloc<String, String> b : load(fileIn))
		{
			out.write(b.getId() + "\n");
			for (int i = 0; i<b.getSize(); i++)
			{
				List<String> lr  = b.getReactions(i);
				List<String> lg  = b.getGenes(i);
				List<Couple<String, String>> l = new ArrayList<Couple<String, String>>();
				for (int j = 0; j<lr.size();j++)
				{
					l.add(new Couple<String, String>(lg.get(j),lr.get(j)));
				}
				out.write("-1\t" + l.size() + "\t" + l + "\n");
			}
			out.write("\n");
		}
		out.close();
	}
}
